package com.cashmama.market.api.application.controller.authentication.personalInfo;

import com.cashmama.market.api.application.controller.authentication.AuthenticationBaseHandler;
import com.cashmama.market.api.application.controller.authentication.AuthenticationController;
import com.cashmama.market.api.application.controller.authentication.personalInfo.vo.BasicInfo;
import com.cashmama.market.api.application.controller.authentication.personalInfo.vo.Reference;
import com.cashmama.market.api.application.controller.authentication.personalInfo.vo.Residence;
import com.cashmama.market.api.application.controller.authentication.response.UserProfileResponse;
import com.cashmama.market.api.application.controller.authentication.vos.AuthenticationContentVo;
import com.cashmama.market.api.application.controller.authentication.vos.InputParams;
import com.cashmama.market.api.application.enums.AuthenticationTypeEnum;
import com.cashmama.market.api.application.enums.ButtonTextEnum;
import com.cashmama.market.api.domain.enums.HomeRouteEnum;
import com.cashmama.market.api.domain.service.ApiUserService;
import com.cashmama.market.api.domain.vo.RequestLocalInfo;
import com.cashmama.market.api.infras.enums.BasicErrorCodeEnum;
import com.cashmama.market.api.infras.enums.JumpRouterEnum;
import com.cashmama.market.api.infras.enums.error.UserProfileErrorCodeEnum;
import com.cashmama.market.api.infras.exception.ApplicationException;
import com.fqgj.common.api.Response;
import com.fqgj.common.utils.EmojiUtil;
import com.fqgj.common.utils.StrUtils;
import com.fqgj.exception.common.ApiIllegalArgumentException;
import com.fqgj.xjd.user.client.UserContactService;
import com.fqgj.xjd.user.client.UserEmailService;
import com.fqgj.xjd.user.client.UserInfoService;
import com.fqgj.xjd.user.client.UserPanService;
import com.fqgj.xjd.user.client.enums.*;
import com.fqgj.xjd.user.client.request.*;
import com.fqgj.xjd.user.client.response.UserAuthEmail;
import com.fqgj.xjd.user.client.response.UserFamilyContact;
import com.fqgj.xjd.user.client.response.UserFriendContact;
import com.qianli.user.enums.UserAuthEnum;
import com.qianli.user.enums.UserAuthStatusEnum;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created with IntelliJ IDEA.
 * User: yujianfu (mr.vencnet@gmail.com)
 * Date: 2019-12-23
 * Time: 09:56
 */
@Service
public class PersonalInfoAuthenticationHandler extends AuthenticationBaseHandler {
    public static final int ADDRESS_MIN_LENGTH = 10;
    public static final int PIN_CODE_LENGTH = 6;

    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private UserContactService userContactService;
    @Autowired
    private UserEmailService userEmailService;
    @Autowired
    private ApiUserService apiUserService;
    @Autowired
    private UserPanService userPanService;

    @PostConstruct
    public void init() {
        AuthenticationController.authenticationBaseHandlerMap.put(AuthenticationTypeEnum.PERSONAL_INFO.getType(), this);
    }

    @Override
    public AuthenticationContentVo content() {

        BasicInfo basicInfo = new BasicInfo();

        AuthenticationContentVo basicDetail = explain(basicInfo);

        Residence residence = new Residence();
        AuthenticationContentVo residenceDetail = explain(residence);

        Reference reference = new Reference();
        AuthenticationContentVo referenceDetail = explain(reference);

        AuthenticationContentVo authenticationContentVo = new AuthenticationContentVo();
        List<InputParams> inputParams = new ArrayList<>();
        inputParams.addAll(basicDetail.getInputParams());
        inputParams.addAll(residenceDetail.getInputParams());
        inputParams.addAll(referenceDetail.getInputParams());
        authenticationContentVo.setInputParams(inputParams);
        authenticationContentVo.setButtonVisibility(true);
        authenticationContentVo.setButtonText(ButtonTextEnum.CONFIRM.getText());
        return authenticationContentVo;
    }


    @Override
    public UserProfileResponse save(Map<String, String> inputParams) {
        BasicInfo basicInfo = new BasicInfo();
        Reference reference = new Reference();
        Residence residence = new Residence();
        getObject(basicInfo, inputParams);
        getObject(reference, inputParams);
        getObject(residence, inputParams);
        doSave(basicInfo, reference, residence);
        UserProfileResponse userProfileResponse = new UserProfileResponse()
                .setJumpUrl(JumpRouterEnum.PERSONAL_INFO_EMPLOYEE.getJumpUrl());
        return userProfileResponse;
    }

    private void doSave(BasicInfo basicInfo, Reference reference, Residence residence){
        validate(basicInfo, reference, residence);
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        UserMarriageEnum userMarriageEnum = UserMarriageEnum.getEnumByType(Integer.valueOf(basicInfo.getMarital().getInputValue()));
        UserResident resident = new UserResident();
        UserBase userBase = new UserBase();
        UserContact userContact = new UserContact();
        resident.setUserCode(userCode)
                .setPinCode(residence.getCurrentPinCode().getInputValue())
                .setAddress(EmojiUtil.filterEmoji(residence.getCurrentAddress().getInputValue()))
                // 永久地址
                .setPermanentPinCode(residence.getPermanentPinCode().getInputValue())
                .setPermanentAddress(EmojiUtil.filterEmoji(residence.getPermanentAddress().getInputValue()));

        userBase.setUserCode(userCode)
                .setMarriedStatus(userMarriageEnum.getType())
                .setStatus(UserBaseStatusEnum.CHECK_SUCCESS.getStatus())
                .setFirstName(basicInfo.getFirstName().getInputValue().trim())
                .setLastName(basicInfo.getLastName().getInputValue().trim())
                .setGender(Integer.valueOf(basicInfo.getGender().getInputValue()))
                .setUserLanguage(Integer.valueOf(basicInfo.getLanguage().getInputValue()))
                .setFatherName(basicInfo.getFatherName().getInputValue().trim())
                .setMotherName(basicInfo.getMatherName().getInputValue().trim())
                .setUsages(1)
                .setBirthday(basicInfo.getDob().getInputValue());

        userContact.setUserCode(userCode).setQq("1");
        userInfoService.addUserContact(userContact);
        //update userContact
        userInfoService.addUserResident(resident);
        //update userProfile
        userInfoService.addUserBase(userBase);
        apiUserService.updateUserAuthStatus(UserAuthStatusEnum.SUCCESS, UserAuthEnum.BASE_INFO_STATUS, RequestLocalInfo.getCurrentUser().getUserCode());

        UserAuthEmail userAuthEmail = new UserAuthEmail()
                .setEmail(basicInfo.getEmail().getInputValue().replaceAll(" ", ""))
                .setUserCode(userCode)
                .setStatus(AuthStatusEnum.AUTH_SUCCESS.getStatus());
        userEmailService.addUserEmail(userAuthEmail);
        apiUserService.updateUserAuthStatus(UserAuthStatusEnum.SUCCESS, UserAuthEnum.EMAIL_STATUS, RequestLocalInfo.getCurrentUser().getUserCode());

        UserPanSaveInfo userPanSaveInfo = new UserPanSaveInfo();
        userPanSaveInfo.setUserCode(userCode);
        userPanSaveInfo.setPanStatus("I");
        userPanService.addUserPan(userPanSaveInfo);

        UserFamilyContact userFamilyContact = null;
        UserFriendContact userFriendContact = null;
        UserContactFamilyTypeEnum userContactFamilyTypeEnum = UserContactFamilyTypeEnum.getEnumByType(Integer.valueOf(reference.getRelations().getInputValue()));
        // 默认为colleague
        UserContactFriendTypeEnum userContactFriendTypeEnum = UserContactFriendTypeEnum.COLLEAGUE;

        if (userContactFamilyTypeEnum == null) {
            throw new ApiIllegalArgumentException(UserProfileErrorCodeEnum.USER_PROFILE_ENUM_TYPE_NOT_EXIST);
        }
        userFamilyContact = new UserFamilyContact(reference.getName().getInputValue().trim(), reference.getMobile().getInputValue().split(":")[0], reference.getMobile().getInputValue().split(":")[1], userContactFamilyTypeEnum);
        userFriendContact = new UserFriendContact(reference.getColleagueName().getInputValue().trim(), reference.getColleagueMobile().getInputValue().split(":")[0], reference.getColleagueMobile().getInputValue().split(":")[1], userContactFriendTypeEnum);

        UserEmergencyContact userEmergencyContact = new UserEmergencyContact(userCode, userFamilyContact, userFriendContact);
        UserEmergencyContact updateContact = buildServiceEmergencyContact(userEmergencyContact);
        Response<Boolean> result = userContactService.addUserEmergencyContact(userEmergencyContact.getUserCode(), updateContact);
        if (!result.isSuccess()) {
            throw new ApplicationException(result.getCode(), result.getMsg());
        }
        apiUserService.updateUserAuthStatus(UserAuthStatusEnum.SUCCESS, UserAuthEnum.BASE_EMERGENCY_STATUS, RequestLocalInfo.getCurrentUser().getUserCode());
    }

    private UserEmergencyContact buildServiceEmergencyContact(UserEmergencyContact userEmergencyContact) {
        UserFriendContact updateFriendContact = null;
        UserFamilyContact updateFamilyContact = null;
        if (userEmergencyContact.getUserFamilyContact() != null) {
            UserFamilyContact contact = userEmergencyContact.getUserFamilyContact();
            Integer type = contact.getUserContactFamilyTypeEnum().getType();

            UserContactFamilyTypeEnum familyTypeEnum
                    = UserContactFamilyTypeEnum.getEnumByType(type);

            updateFamilyContact = new UserFamilyContact(contact.getName(),
                    contact.getContactName(), contact.getMobile(), familyTypeEnum);
        }
        if (userEmergencyContact.getUserFriendContact() != null) {
            UserFriendContact contact = userEmergencyContact.getUserFriendContact();
            Integer type = contact.getUserContactFriendTypeEnum().getType();

            UserContactFriendTypeEnum friendTypeEnum
                    = UserContactFriendTypeEnum.getEnumByType(type);

            updateFriendContact = new UserFriendContact(contact.getName(),
                    contact.getContactName(), contact.getMobile(), friendTypeEnum);
        }
        UserEmergencyContact updateContact =
                new UserEmergencyContact(userEmergencyContact.getUserCode(),
                        updateFamilyContact, updateFriendContact);
        return updateContact;
    }

    private void validate(BasicInfo basicInfo, Reference reference, Residence residence) {
        String mobile = RequestLocalInfo.getCurrentUser().getMobile();
        if (StringUtils.isBlank(basicInfo.getFirstName().getInputValue())) {
            throw new ApplicationException("First Name should not be empty");
        }
        if (StringUtils.isBlank(basicInfo.getDob().getInputValue())) {
            throw new ApplicationException("DOB should not be empty");
        }
        if (StringUtils.isBlank(basicInfo.getLastName().getInputValue())) {
            throw new ApplicationException("Last Name should not be empty");
        }
        if (Objects.equals(basicInfo.getFirstName().getInputValue(), basicInfo.getLastName().getInputValue())) {
            throw new ApplicationException("Last name shouldn't same as the first name");
        }
        if (StringUtils.isBlank(basicInfo.getFatherName().getInputValue())) {
            throw new ApplicationException("Father's Name should not be empty");
        }
        if (StringUtils.isBlank(basicInfo.getMatherName().getInputValue())) {
            throw new ApplicationException("Mother's Name should not be empty");
        }
        if (!StrUtils.isNumeric(basicInfo.getGender().getInputValue())) {
            throw new ApplicationException("Gender should not be empty");
        }
        if (!StrUtils.isNumeric(basicInfo.getLanguage().getInputValue())) {
            throw new ApplicationException("Language should not be empty");
        }
        if (!StrUtils.isNumeric(basicInfo.getMarital().getInputValue())) {
            throw new ApplicationException("Marital Status should not be empty");
        }
        if(StringUtils.isBlank(basicInfo.getEmail().getInputValue())){
            throw new ApplicationException("Email should not be empty");
        }

        String check = "^[A-Za-z0-9]+([_\\.][A-Za-z0-9]+)*@([A-Za-z0-9\\-]+\\.)+[A-Za-z]{2,6}$";
        Pattern regex = Pattern.compile(check);
        Matcher matcher = regex.matcher(basicInfo.getEmail().getInputValue().replaceAll(" ", ""));
        if (!matcher.matches()) {
            throw new ApplicationException("Please enter the correct email");
        }


        if (!StrUtils.isNumeric(residence.getCurrentPinCode().getInputValue()) || residence.getCurrentPinCode().getInputValue().length() != PIN_CODE_LENGTH) {
            throw new ApplicationException("Please enter the correct pinCode");
        }
        if (StringUtils.isBlank(residence.getCurrentAddress().getInputValue())) {
            throw new ApplicationException("Address should not be empty");
        }
        if (residence.getCurrentAddress().getInputValue().trim().length() < ADDRESS_MIN_LENGTH || residence.getCurrentAddress().getInputValue().contains("@")) {
            throw new ApplicationException("Please enter the correct address");
        }
        String permanentAddress = EmojiUtil.filterEmoji(residence.getPermanentAddress().getInputValue());
        if (StringUtils.isBlank(permanentAddress)) {
            throw new ApplicationException("Permanent Address should not be empty");
        }
        if (permanentAddress.trim().length() < ADDRESS_MIN_LENGTH || permanentAddress.contains("@")) {
            throw new ApplicationException("Please enter the correct permanent address");
        }
        if (!StrUtils.isNumeric(residence.getPermanentPinCode().getInputValue()) || residence.getPermanentPinCode().getInputValue().length() != PIN_CODE_LENGTH) {
            throw new ApplicationException("Please enter the correct permanent pinCode");
        }

        //紧急联系人
        if (!StrUtils.isNumeric(reference.getRelations().getInputValue())) {
            throw new ApplicationException("Relations should not be empty");
        }
        if (StringUtils.isBlank(reference.getName().getInputValue())) {
            throw new ApplicationException("Please enter the correct name");
        }
        if (StringUtils.isBlank(reference.getColleagueName().getInputValue())) {
            throw new ApplicationException("Please enter the correct name");
        }
        String numberRegex = "[0-9]+";
        if (reference.getName().getInputValue().matches(numberRegex)) {
            throw new ApplicationException("Please enter the correct name");
        }
        if (reference.getColleagueName().getInputValue().matches(numberRegex)) {
            throw new ApplicationException("Please enter the correct name");
        }

        //客户端传入手机号形式为 contacts.name+":"+contacts.mobile
        if(StringUtils.isNotBlank(reference.getMobile().getInputValue()) && !reference.getMobile().getInputValue().contains(":")){
            throw new ApplicationException("Please enter the correct mobile like \'param:param\'");
        }
        if(StringUtils.isNotBlank(reference.getColleagueMobile().getInputValue()) && !reference.getColleagueMobile().getInputValue().contains(":")){
            throw new ApplicationException("Please enter the correct colleague mobile like \'param:param\'");
        }

        String mobileRegex = ".*[a-zA-Z]+.*";
        if (StringUtils.isBlank(reference.getMobile().getInputValue()) || reference.getMobile().getInputValue().split(":")[1].matches(mobileRegex)) {
            throw new ApplicationException("Please enter the correct contact phone");
        }
        if (StringUtils.isBlank(reference.getColleagueMobile().getInputValue()) || reference.getColleagueMobile().getInputValue().split(":")[1].matches(mobileRegex)) {
            throw new ApplicationException("Please enter the correct contact phone");
        }
        if (reference.getMobile().getInputValue().split(":")[1].equals(reference.getColleagueMobile().getInputValue().split(":")[1])) {
            throw new ApplicationException("Please enter the different phone for your colleague");
        }
        if (reference.getMobile().getInputValue().split(":")[1].equals(mobile) || reference.getColleagueMobile().getInputValue().split(":")[1].equals(mobile)) {
            throw new ApiIllegalArgumentException("The phone number cant not be the same as yours");
        }
    }
}
